import axios, {
  AxiosResponse,
  AxiosRequestHeaders,
  AxiosRequestConfig,
} from 'axios';
import environment from "@/environment";
import IStorage from "@/services/storage.service";
import { defer, Observable, map, of, delay, catchError } from 'rxjs';
import { history, Link } from '@umijs/max';
import { message } from "antd"
import IHelper from "@/services/helper.service";

export interface IAxiosResponse {
  status: boolean;
  message: string;
  code: number;
  data: any;
  timestamp: number;
  requestConfig?: IAxiosRequestConfig;
}
export interface IAxiosRequestConfig extends AxiosRequestConfig {
  url: string;
  strictJson?: boolean;
  delay?: number;
  skipErrorHandler?: boolean
}

class IError extends Error {
  code: number;
  constructor(message: string, code?: number) {
    super(message);
    this.code = code || 500;
  }
}

const IHttp = new class Http {
  get(config: IAxiosRequestConfig): Observable<IAxiosResponse> {
    return this.buildRequest({ ...config, method: 'GET' });
  }
  post(config: IAxiosRequestConfig): Observable<IAxiosResponse> {
    return this.buildRequest({ ...config, method: 'POST' });
  }
  buildJwtHeaders(ticket: string) {
    return {"Authorization": `Bearer ${ticket}`}
  }
  buildHeaders(config: IAxiosRequestConfig): AxiosRequestHeaders {
    let jwtHeaders = IStorage.getUserTicket() ? this.buildJwtHeaders(IStorage.getUserTicket()) : {}
    const mixedHeaders = { ...jwtHeaders, ...config.headers };
    return mixedHeaders as AxiosRequestHeaders;
  }
  buildUrl(config: IAxiosRequestConfig): string | undefined {
    return config.url.startsWith('http')
      ? config.url
      : `${environment.apiDomain}${config.url}`;
  }
  buildResponse(
    config: IAxiosRequestConfig,
  ): (response: AxiosResponse) => IAxiosResponse {
    return (response: AxiosResponse) => {
      if (response.status < 200 || response.status > 299) {
        throw new IError('网络错误', response.status);
      }
      try {
        JSON.parse(JSON.stringify(response.data));
      } catch (error) {
        throw new IError('解析错误', 500);
      }
      let data: any = response.data;
      return { ...data, requestConfig: config } as IAxiosResponse;
    };
  }
  buildError(
    config: IAxiosRequestConfig,
  ): (error: any) => Observable<IAxiosResponse> {
    return (error: any) => {
      return of({
        status: false,
        message: error.message || '网络错误',
        data: null,
        code: error?.code || 500,
        timestamp: Date.now(),
        requestConfig: config,
      });
    };
  }
  buildRequest(config: IAxiosRequestConfig): Observable<IAxiosResponse> {
    return defer(() =>
      axios({
        ...config,
        url: this.buildUrl(config),
        headers: this.buildHeaders(config),
      }),
    ).pipe(
      // delay(1000),
      map(this.buildResponse(config)),
      catchError(this.buildError(config)),
      map(res => {
        const skipErrorHandler: boolean = config.skipErrorHandler === true
        if (!skipErrorHandler && !res.status) {
          message.error(res.message).then(e => e)
        }
        if (!res.status && res.code === 401 && !skipErrorHandler) {
          IHelper.linkToLogin()
        }
        return res
      }),
    );
  }

  uploadFile(config: Partial<IAxiosRequestConfig>) {
    // const formData = new FormData()
    // formData.append("file", file)
    // Object.keys(data || {}).forEach(k => {
    //   formData.append(k, (data || {})[k])
    // })
    return this.post({...config, url: `/shared/upload`})
  }

  getCurrentUser(opt?: Partial<IAxiosRequestConfig>) {
    return this.get({url: "/auth/user", ...opt})
  }

  login(data: API.LoginParams) {
    return this.post({url: "/auth/login", data})
  }

  getAccountList(opt?: API.QueryFilterParams & {keyword?: string}) {
    const params: {[prop: string]: any} = {
      page: opt?.page || 1, pageSize: opt?.pageSize || environment.pageSize,
    }
    if (opt?.keyword) {
      params["keyword"] = opt?.keyword
    }
    return this.get({url: `/account/list`, params})
  }

  createAccount(data: Partial<API.AccountItem>) {
    return this.post({url: "/account/create", data})
  }

  updateAccount(id: number, data: Partial<API.AccountItem>) {
    return this.post({url: `/account/${id}/update`, data})
  }

  delAccount(id: number) {
    return this.post({url: `/account/${id}/delete`})
  }

  getAccountPosts(id: number | string, params?: API.QueryFilterParams) {
    return this.get({url: `/account/${id}/posts`, params})
  }

  bindAccountPrepare(id: number) {
    return this.get({url: `/account/${id}/bind/prepare`})
  }

  bindAccountCheck(id: number, params: {hash: string}) {
    return this.get({url: `/account/${id}/bind/check`, params})
  }

  getVideoList(opt?: API.QueryFilterParams & {keyword?: string, type?: number}) {
    const params: {[prop: string]: any} = {
      page: opt?.page || 1, pageSize: opt?.pageSize || environment.pageSize,
      type: []
    }
    if (opt?.keyword) {
      params["keyword"] = opt?.keyword
    }
    return this.get({url: `/video/list`, params})
  }

  createVideo(data: Partial<API.VideoItem>) {
    return this.post({url: `/video/create`, data})
  }
  updateVideo(id: number, data: Partial<API.VideoItem>) {
    return this.post({url: `/video/${id}/update`, data})
  }
  delVideo(id: number) {
    return this.post({url: `/video/${id}/delete`})
  }

  getVideoInfo(id: number) {
    return this.get({url: `/video/${id}/info`})
  }

  fireVideo(id: number, data: any) {
    return this.post({url: `/video/${id}/fire`, data})
  }

  getVideoSuffixList() {
    return this.get({url: `/video/suffix/list`})
  }

  getVideoCutTemplateList(opt?: API.QueryFilterParams & {keyword?: string, type?: number}) {
    const params: {[prop: string]: any} = {
      page: opt?.page || 1, pageSize: opt?.pageSize || environment.pageSize,
      type: []
    }
    if (opt?.keyword) {
      params["keyword"] = opt?.keyword
    }
    return this.get({url: `/video/cut-template/list`, params})
  }

  createVideoCutTemplate(data: Partial<API.VideoItem>) {
    return this.post({url: `/video/cut-template/create`, data})
  }
  updateVideoCutTemplate(id: number, data: Partial<API.VideoItem>) {
    return this.post({url: `/video/cut-template/${id}/update`, data})
  }
  delVideoCutTemplate(id: number) {
    return this.post({url: `/video/cut-template/${id}/delete`})
  }

  getPubTemplateList(opt?: API.QueryFilterParams) {
    const params: {[prop: string]: any} = {
      page: opt?.page || 1, pageSize: opt?.pageSize || environment.pageSize,
    }
    if (opt?.keyword) {
      params["keyword"] = opt.keyword
    }
    return this.get({url: `/pub/template/list`, params})
  }

  createPubTemplate(data: Partial<API.PubTemplateItem>) {
    return this.post({url: `/pub/template/create`, data})
  }
  updatePubTemplate(id: number, data: Partial<API.PubTemplateItem>) {
    return this.post({url: `/pub/template/${id}/update`, data})
  }
  delPubTemplate(id: number) {
    return this.post({url: `/pub/template/${id}/delete`})
  }

  getPubTaskSettings() {
    return this.get({url: `/pub/task/settings`})
  }

  setPubTaskSettings(settings: any) {
    return this.post({url: `/pub/task/settings`, data: settings})
  }

  getPubTaskList(opt?: API.QueryFilterParams) {
    const params: {[prop: string]: any} = {
      page: opt?.page || 1, pageSize: opt?.pageSize || environment.pageSize,
    }
    if (opt?.keyword) {
      params["keyword"] = opt.keyword
    }
    return this.get({url: `/pub/task/list`, params})
  }

  createPubTask(data: Partial<API.PubTemplateItem>) {
    return this.post({url: `/pub/task/create`, data})
  }

  createMultiplePubTask(id: number, data: any) {
    return this.post({url: `/pub/task/${id}/create_multiple`, data})
  }

  updatePubTask(id: number, data: Partial<API.PubTaskItem>) {
    return this.post({url: `/pub/task/${id}/update`, data})
  }
  delPubTask(id: number) {
    return this.post({url: `/pub/task/${id}/delete`})
  }

  getGetVideoQueue() {
    return this.get({url: `/pub/task/get_video/queue`})
  }

  delManyPubTask(ids: number[]) {
    return this.post({url: `/pub/task/delete_many`, data: ids})
  }

  startPubTask(id: number, selected_accounts?: string) {
    return this.post({url: `/pub/task/${id}/start`, data: {selected_accounts}})
  }

  getTaskVideoAsync(ids: number[], config: any) {
    console.error("13131", ids, config)
    return this.post({url: `/pub/task/get_video/async`, data: {config, ids}})
  }

  copyPubTask(id: number) {
    return this.post({url: `/pub/task/${id}/copy`})
  }

  getAccountTypeVars() {
    return this.get({url: "/account/type_vars"})
  }

  getBiliTypeList() {
    return this.get({url: "/bili/typelist"})
  }

  getKsTypeList() {
    return this.get({url: "/ks/typelist"})
  }
  suggestDyTag(keyword: string) {
    return this.get({url: `/dy/suggest/tag?keyword=${keyword}`})
  }

  accountSmsSend(id: number) {
    return this.post({url: `/account/${id}/sms/send`})
  }
  accountSmsValidate(id: number, code: string) {
    return this.post({url: `/account/${id}/sms/validate?code=${code}`})
  }
  shareAccountCookie(id: number, cookie: string, ticket: string) {
    return this.post({url: `https://vpuber-api.wonew.top/account/${id}/share/cookie`, data: {cookie}, headers: this.buildJwtHeaders(ticket)})
  }
  checkAccountCookie(id: number) {
    return this.get({url: `/account/${id}/check-cookie`})
  }
  openAccountHomePage(id: number) {
    return this.get({url: `/account/${id}/open-home-page`})
  }
  closeAccountHomePage(hashId: string) {
    return this.get({url: `/account/close-home-page/${hashId}`})
  }
  updateAccountHookUserAction(id: number) {
    return this.post({url: `/account/${id}/update-hook-user-action`})
  }
}

export default IHttp;

// export default $http;
